#include "cppTutorUnique_Ptr.h"

// trace log
#include "cppTutorLog.h"
extern CcppTutorLog Log;

using namespace std;

class CUniquePtrDemo;

void uniquePtr () {
    Log << "ENTER : uniquePtr ()" << endl;

    cout << "Creating a new unique_ptr 'up' of type int and assigning a value 1729 to it" << endl;

    unique_ptr <int> up (new int (1729));
    cout << *up << endl;

    cout << endl;
    cout << "------------------------" << endl;
    cout << "         move           " << endl;
    cout << "------------------------" << endl;
    cout << endl;
    cout << "Crteaing a new unique_ptr 'up2' and moving the content of 'up' to it" << endl;
    unique_ptr <int> up2 = move (up);
    
    cout << "Checking if 'up' is NULL now" << endl;
    if (up){
        cout << "We got a serious problem here !!!" << endl;
    }
    else {
        cout << "Bingo !!!" << endl;
    }
    
    cout << "content of up2 is : " << *up2 << endl;
    
    cout << "Creating an object of a class now" << endl;
    unique_ptr <CUniquePtrDemo> upd (new CUniquePtrDemo ());
    upd->m_getValue();
    
    cout << endl;
    cout << "------------------------" << endl;
    cout << "std::unique_ptr::release" << endl;
    cout << "------------------------" << endl;
    cout << endl;
    int *npX = NULL;
    npX = up2.release (); 
    // up2 is null now, just do an informative check
    if (up2 == NULL) {
        cout << "up2 is NULL now" << endl;
    }
    else {
        cout << "Something went wrong !!!" << endl;
    }
    cout << "npX = " << *npX << endl;
    
    cout << endl;
    cout << "------------------------" << endl;
    cout << " std::unique_ptr::reset " << endl;
    cout << "------------------------" << endl;
    cout << endl;    
    unique_ptr <int> up3 (new int (1000));
    up3.reset (new int);    
    *up3 = 999;
    Log << "EXIT  : uniquePtr ()" << endl;
}

CUniquePtrDemo :: CUniquePtrDemo () : m_nTest (10) {
    Log << "ENTER : CUniquePtrDemo :: CUniquePtrDemo ()" << endl;
    Log << "EXIT  : CUniquePtrDemo :: CUniquePtrDemo ()" << endl;
}

CUniquePtrDemo :: ~CUniquePtrDemo (){
    Log << "ENTER : CUniquePtrDemo :: ~CUniquePtrDemo ()" << endl;
    Log << "EXIT  : CUniquePtrDemo :: ~CUniquePtrDemo ()" << endl;
}

void CUniquePtrDemo :: m_getValue () {
    Log << "ENTER : CUniquePtrDemo :: m_getValue ()" << endl;
    cout << "checking the private data member with the object created : " << m_nTest << endl;
    Log << "EXIT  : CUniquePtrDemo :: m_getValue ()" << endl;
}